﻿#include "GY_GraphicsPolygonRegular.h"
#define PI 3.14159265359

GY_GraphicsPolygonRegular::GY_GraphicsPolygonRegular(const QString &guid, QGraphicsItem *parent)
    :GY_BasicsGraphicsObject(guid,this,parent)
{
    //图元类型
    GY_Object::setUserData(GY_ENUM::ClassType,QVariant("PolygonRegular"));
    initializationPropertyInfo();
    QPointF firstPoint=m_PropertyInfoMap.value("FirstPoint").propertyValue.value<QPointF>();

    QMap<QVariant,QPointF> editPoints = {{"FirstPoint",firstPoint}};
    updatePath();
    this->setEditPointF(editPoints);
    this->setCenterPointF(m_PropertyInfoMap["Center"].propertyValue.toPointF());

}

GY_GraphicsPolygonRegular::GY_GraphicsPolygonRegular(const QString &guid,
                                                     const QPointF &centerPoint,
                                                     const QPointF &firstPoint,
                                                     const int &numberOfPoints,
                                                     QGraphicsItem *parent)
    :GY_BasicsGraphicsObject(guid,this,parent)
{
    //图元类型
    GY_Object::setUserData(GY_ENUM::ClassType,QVariant("PolygonRegular"));
    initializationPropertyInfo();
    m_PropertyInfoMap["Center"].propertyValue=centerPoint;
    m_PropertyInfoMap["FirstPoint"].propertyValue=firstPoint;
//    QMap<QVariant,QPointF> editPoints = {{"Center",centerPoint},{"FirstPoint",firstPoint}};
    QMap<QVariant,QPointF> editPoints = {{"FirstPoint",firstPoint}};
    updatePath();
    this->setPen(QColor(0,255,0));
    this->setEditPointF(editPoints);
    this->setCenterPointF(m_PropertyInfoMap["Center"].propertyValue.toPointF());
}

GY_GraphicsPolygonRegular::~GY_GraphicsPolygonRegular()
{

}

bool GY_GraphicsPolygonRegular::updateCenter(const QString &name, const QVariant &value)
{//单独改变centerPoint坐标时firstPoint坐标不变（此时两点相对位置会变但距离不一定发生变化）
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    //从屏幕获取鼠标坐标
    QPointF mousePoint = this->mapFromScene(value.value<QPointF>());
    m_PropertyInfoMap[name].propertyValue = mousePoint;
    this->setCenterPointF(value.toPointF());
    updatePath();

    return true;
}

bool GY_GraphicsPolygonRegular::updateFirstPoint(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>()){
        return false;
    }
    //从屏幕获取鼠标坐标
    QPointF mousePoint = this->mapFromScene(value.value<QPointF>());
    m_PropertyInfoMap[name].propertyValue = mousePoint;
    //设置点（设置单个点）
    this->setEditPointF("FirstPoint",mousePoint);
    updatePath();
    return true;
}

bool GY_GraphicsPolygonRegular::updateNumberOfPoints(const QString &name, const QVariant &value)
{
    if(!value.canConvert<int>() || (value.toInt() < 3 || value.toInt() > 100)){
        return false;
    }
    //顶点数=中线数=边数，可用于确定边数
    m_PropertyInfoMap[name].propertyValue=value;
    updatePath();
    return true;
}

void GY_GraphicsPolygonRegular::updatePath()
{    
    //取出已初始化的numberOfPoints
    int numberOfPoints = m_PropertyInfoMap["NumberOfPoints"].propertyValue.toInt();//改值
    //取与计算有关的值
    QPointF firstPoint = m_PropertyInfoMap["FirstPoint"].propertyValue.toPointF();
    QPointF centerPoint = m_PropertyInfoMap["Center"].propertyValue.toPointF();
    //计算中线之间形成的中心角，再结合两点之间形成的半径求出各点位置并连接成为图形
    //!
    //! \brief alpha 注意角度的精度问题，应该取数据类型为float的360.0来除以整数，而非用360作被除数
    //!
    qreal alpha = 360.0/numberOfPoints;//计算中心角
    QPointF point;//=m_PropertyInfoMap.value(QString("point[%1]").arg(numberOfPoints-i)).propertyValue.value<QPointF>();
    //根据centerPoint坐标和radius半径求任一顶点坐标
    QPainterPath path;
    path.moveTo(firstPoint);
    //绘制线段与其他顶点相连接形成正多边形
    for(int i = 0;i<numberOfPoints-1;i++)
    {
        //角度
        qreal angel = qDegreesToRadians((i+1)*alpha);
        /*除了firstPoint之外其余顶点的横纵轴值*/
        //!注意代码书写风格，运算符号前后空一格便于区分和纠错
        //! 注意：由于是为了便于计算而参考原点为图形圆心，所以若要更改圆心到其他点则需要加上偏移量，即为centerPoint的横纵坐标
        point.setX((firstPoint.x()-centerPoint.x())*qCos(angel) - (firstPoint.y()-centerPoint.y())*qSin(angel) + centerPoint.x());
        point.setY((firstPoint.x()-centerPoint.x())*qSin(angel) + (firstPoint.y()-centerPoint.y())*qCos(angel) + centerPoint.y());
//        m_PropertyInfoMap[QString("point[%1]").arg(numberOfPoints-i)].propertyValue = point;
        path.lineTo(point);
    }
    //闭合图形
    path.closeSubpath();
    //绘制图形
    this->setPath(path);
}

void GY_GraphicsPolygonRegular::initializationPropertyInfo()
{    
    QPointF Position = QPointF(0,0);//开始的坐标或中心点坐标
    QPointF Point = QPointF(1,1);//结束的坐标或径向梯度的焦点坐标
    QVector<qreal> varGradientStyle;
    varGradientStyle<<Position.x()<<Position.y()<<Point.x()<<Point.y();

    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap["ObjectName"].setConnect();

    GY_PropertyInfo IsVisible(this);
    IsVisible.propertyName = "IsVisible";
    IsVisible.propertyValue = true;
    IsVisible.updateType = Update|OrdinaryAttributes;
    IsVisible.propertyType = BoolPropertyType;
    IsVisible.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateIsVisible;
    m_PropertyInfoMap.insert("IsVisible",IsVisible);
    m_PropertyInfoMap["IsVisible"].setConnect();

    GY_PropertyInfo IsOutLined(this);
    IsOutLined.propertyName = "IsOutlined";
    IsOutLined.propertyValue = true;
    IsOutLined.updateType = Update|OrdinaryAttributes;
    IsOutLined.propertyType = BoolPropertyType;
    IsOutLined.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateIsOutLined;
    m_PropertyInfoMap.insert("IsOutlined",IsOutLined);
    m_PropertyInfoMap["IsOutlined"].setConnect();

    GY_PropertyInfo IsFilled(this);
    IsFilled.propertyName = "IsFilled";
    IsFilled.propertyValue = true;
    IsFilled.updateType = Update|OrdinaryAttributes;
    IsFilled.propertyType = BoolPropertyType;
    IsFilled.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateIsFilled;
    m_PropertyInfoMap.insert("IsFilled",IsFilled);
    m_PropertyInfoMap["IsFilled"].setConnect();

    GY_PropertyInfo IsAntialiased(this);
    IsAntialiased.propertyName = "IsAntialiased";
    IsAntialiased.propertyValue = false;
    IsAntialiased.updateType = Update|OrdinaryAttributes;
    IsAntialiased.propertyType = BoolPropertyType;
    IsAntialiased.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateIsAntialiased;
    m_PropertyInfoMap.insert("IsAntialiased",IsAntialiased);
    m_PropertyInfoMap["IsAntialiased"].setConnect();

    GY_PropertyInfo FillAttributes(this);
    FillAttributes.propertyName = "FillAttributes";
    FillAttributes.propertyValue = false;
    FillAttributes.updateType = Update|OrdinaryAttributes;
    FillAttributes.propertyType = BoolPropertyType;
    FillAttributes.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateFillAttributes;
    m_PropertyInfoMap.insert("FillAttributes",FillAttributes);
    m_PropertyInfoMap["FillAttributes"].setConnect();

    GY_PropertyInfo FillGradient(this);
    FillGradient.propertyName = "FillGradient";
    FillGradient.propertyValue = QVariant();
    FillGradient.updateType = Update|OrdinaryAttributes;
    FillGradient.propertyType = FillGradientPropertyType;
    FillGradient.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateFillGradient;
    m_PropertyInfoMap.insert("FillGradient",FillGradient);
    m_PropertyInfoMap["FillGradient"].setConnect();

    GY_PropertyInfo FillColor(this);
    FillColor.propertyName = "FillColor";
    FillColor.propertyValue = QColor();
    FillColor.updateType = Update|OrdinaryAttributes;
    FillColor.propertyType = ColorPropertyType;
    FillColor.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateFillColor;
    m_PropertyInfoMap.insert("FillColor",FillColor);
    m_PropertyInfoMap["FillColor"].setConnect();

    GY_PropertyInfo FillStyle(this);
    FillStyle.propertyName = "FillStyle";
    FillStyle.propertyValue = true;
    FillStyle.updateType = Update|OrdinaryAttributes;
    FillStyle.propertyType = FillStylePropertyType;
    FillStyle.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateFillStyle;
    m_PropertyInfoMap.insert("FillStyle",FillStyle);
    m_PropertyInfoMap["FillStyle"].setConnect();

    GY_PropertyInfo FillOpacity(this);
    FillOpacity.propertyName = "FillOpacity";
    FillOpacity.propertyValue = 1;
    FillOpacity.updateType = Update|OrdinaryAttributes;
    FillOpacity.propertyType = QrealPropertyType;
    FillOpacity.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateFillOpacity;
    m_PropertyInfoMap.insert("FillOpacity",FillOpacity);
    m_PropertyInfoMap["FillOpacity"].setConnect();

    GY_PropertyInfo Pattern(this);
    Pattern.propertyName = "Pattern";
    Pattern.propertyValue = QVariant();
    Pattern.updateType = Update|OrdinaryAttributes;
    Pattern.propertyType = PatternPropertyType;
    Pattern.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updatePattern;
    m_PropertyInfoMap.insert("Pattern",Pattern);
    m_PropertyInfoMap["Pattern"].setConnect();

    GY_PropertyInfo PenColor(this);
    PenColor.propertyName = "PenColor";
    PenColor.propertyValue = QColor();
    PenColor.updateType = Update|OrdinaryAttributes;
    PenColor.propertyType = ColorPropertyType;
    PenColor.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updatePenColor;
    m_PropertyInfoMap.insert("PenColor",PenColor);
    m_PropertyInfoMap["PenColor"].setConnect();

    GY_PropertyInfo PenAttributes(this);
    PenAttributes.propertyName = "PenAttributes";
    PenAttributes.propertyValue = false;
    PenAttributes.updateType = Update|OrdinaryAttributes;
    PenAttributes.propertyType = BoolPropertyType;
    PenAttributes.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updatePenAttributes;
    m_PropertyInfoMap.insert("PenAttributes",PenAttributes);
    m_PropertyInfoMap["PenAttributes"].setConnect();

    GY_PropertyInfo PenOpacity(this);
    PenOpacity.propertyName = "PenOpacity";
    PenOpacity.propertyValue = 1;
    PenOpacity.updateType = Update|OrdinaryAttributes;
    PenOpacity.propertyType = IntPropertyType;
    PenOpacity.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updatePenOpacity;
    m_PropertyInfoMap.insert("PenOpacity",PenOpacity);
    m_PropertyInfoMap["PenOpacity"].setConnect();

    GY_PropertyInfo LineStyle(this);
    LineStyle.propertyName = "LineStyle";
    QVector<qreal> lineStyle;
    int style = Qt::SquareCap|Qt::BevelJoin|Qt::CustomDashLine;
    lineStyle<<style<<2<<3<<4<<5<<6<<7;//自定义矩形线框样式
    LineStyle.propertyValue = QVariant::fromValue(lineStyle);
    LineStyle.updateType = Update|OrdinaryAttributes;
    LineStyle.propertyType = LineStylePropertyType;
    LineStyle.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateLineStyle;
    m_PropertyInfoMap.insert("LineStyle",LineStyle);
    m_PropertyInfoMap["LineStyle"].setConnect();

    GY_PropertyInfo Center(this);//Center
    Center.propertyName = "Center";
    Center.propertyValue = QPointF(20,20);//0,0
    Center.updateType = Update|MoveUpdate|PointOfRelative;
    Center.propertyType = PointPropertyType;
    Center.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateCenter;
    m_PropertyInfoMap.insert("Center",Center);
    m_PropertyInfoMap["Center"].setConnect();

    GY_PropertyInfo FirstPoint(this);//FirstPoint
    FirstPoint.propertyName = "FirstPoint";
    FirstPoint.propertyValue = QPointF(30,30);//100,100
    FirstPoint.updateType = Update|MoveUpdate|PointOfRelative;
    FirstPoint.propertyType = PointPropertyType;
    FirstPoint.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateFirstPoint;
    m_PropertyInfoMap.insert("FirstPoint",FirstPoint);
    m_PropertyInfoMap["FirstPoint"].setConnect();

    GY_PropertyInfo NumberOfPoints(this);//NumberOfPoints
    NumberOfPoints.propertyName = "NumberOfPoints";
    NumberOfPoints.propertyValue = int(5);//5
    NumberOfPoints.updateType = Update|OrdinaryAttributes;
    NumberOfPoints.propertyType = IntPropertyType;
    NumberOfPoints.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonRegular::updateNumberOfPoints;
    m_PropertyInfoMap.insert("NumberOfPoints",NumberOfPoints);
    m_PropertyInfoMap["NumberOfPoints"].setConnect();
}
